home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / cross / devpic.lha / devpic / source / picasm / pic12bit.c < prev    next >
C/C++ Source or Header  |  2000-02-27  |  5KB  |  248 lines

  1. /*
  2.  * picasm -- pic12bit.c
  3.  *
  4.  * Timo Rossi <trossi@iki.fi>
  5.  * 
  6.  */
  7.  
  8. #include <stdio.h>
  9.  
  10. #include "picasm.h"
  11.  
  12. /*
  13.  * Assemble 12-bit PIC code
  14.  *
  15.  */
  16. int
  17. assemble_12bit_mnemonic(int op)
  18. {
  19.   long val;
  20.   struct symbol *sym;
  21.   char *cp;
  22.   int t, symtype;
  23.  
  24.   switch(op) {
  25.     case KW_ANDLW:
  26.     case KW_IORLW:
  27.     case KW_XORLW:
  28.       val = get_expression();
  29.       if(expr_error)
  30.     return FAIL;
  31.       if(val < -0x80 || val > 0xff)
  32.     error(1, "8-bit literal out of range");
  33.       val &= 0xff; /* this assumes 2-complement negative numbers */
  34.       switch(op) {
  35.         case KW_ANDLW: gen_code(0xe00 | val); break;
  36.     case KW_IORLW: gen_code(0xd00 | val); break;
  37.     case KW_XORLW: gen_code(0xf00 | val); break;
  38.       }
  39.       break;
  40.  
  41.     case KW_MOVLW:
  42.       if(gen_byte_c(0xc00) != OK)
  43.     return FAIL;
  44.       break;
  45.  
  46.     case KW_ADDWF:
  47.     case KW_SUBWF:
  48.     case KW_ANDWF:
  49.     case KW_IORWF:
  50.     case KW_XORWF:
  51.     case KW_COMF:
  52.     case KW_DECF:
  53.     case KW_INCF:
  54.     case KW_MOVF:
  55.     case KW_DECFSZ:
  56.     case KW_INCFSZ:
  57.     case KW_RLF:
  58.     case KW_RRF:
  59.     case KW_SWAPF:
  60.       val = get_expression();
  61.       if(expr_error)
  62.     return FAIL;
  63.       if(val < 0 || val > 0x1f)
  64.     error(0, "Register file address out of range");
  65.       t = 1;
  66.       if(token_type == TOK_COMMA) {
  67.     get_token();
  68.     t = get_expression();
  69.     if(expr_error)
  70.       return FAIL;
  71.       }    else {
  72.     if(warnlevel > 0)
  73.       warning("Destination speficier omitted");
  74.       }
  75.       val = (val & 0x1f) | (t != 0 ? 0x20 : 0);
  76.       switch(op) {
  77.         case KW_ADDWF:  gen_code(0x1c0 | val); break;
  78.     case KW_SUBWF:  gen_code(0x080 | val); break;
  79.     case KW_ANDWF:  gen_code(0x140 | val); break;
  80.     case KW_IORWF:  gen_code(0x100 | val); break;
  81.     case KW_XORWF:  gen_code(0x180 | val); break;
  82.     case KW_COMF:   gen_code(0x240 | val); break;
  83.     case KW_DECF:   gen_code(0x0c0 | val); break;
  84.     case KW_INCF:   gen_code(0x280 | val); break;
  85.     case KW_MOVF:   gen_code(0x200 | val); break;
  86.     case KW_DECFSZ: gen_code(0x2c0 | val); break;
  87.     case KW_INCFSZ: gen_code(0x3c0 | val); break;
  88.     case KW_RLF:    gen_code(0x340 | val); break;
  89.     case KW_RRF:    gen_code(0x300 | val); break;
  90.     case KW_SWAPF:  gen_code(0x380 | val); break;
  91.       }
  92.       break;
  93.  
  94.     case KW_CLRF:
  95.     case KW_MOVWF:
  96.       val = get_expression();
  97.       if(expr_error)
  98.     return FAIL;
  99.       if(val < 0 || val > 0x1f)
  100.     error(0, "Register file address out of range");
  101.       switch(op) {
  102.         case KW_CLRF:  gen_code(0x060 | val); break;
  103.     case KW_MOVWF: gen_code(0x020 | val); break;
  104.       }
  105.       break;
  106.  
  107.     case KW_BCF:
  108.     case KW_BSF:
  109.     case KW_BTFSC:
  110.     case KW_BTFSS:
  111.       val = get_expression();
  112.       if(expr_error)
  113.     return FAIL;
  114.       if(val < 0 || val > 0x1f)
  115.     error(0, "Register file address out of range");
  116.       if(token_type != TOK_COMMA) {
  117.     error(1, "',' expected");
  118.     return FAIL;
  119.       }
  120.       get_token();
  121.       t = get_expression();
  122.       if(expr_error)
  123.     return FAIL;
  124.       if(t < 0 || t > 7) {
  125.     error(0, "Bit number out of range");
  126.       }
  127.       val |= (t << 5);
  128.       switch(op) {
  129.         case KW_BCF:   gen_code(0x400 | val); break;
  130.     case KW_BSF:   gen_code(0x500 | val); break;
  131.     case KW_BTFSC: gen_code(0x600 | val); break;
  132.     case KW_BTFSS: gen_code(0x700 | val); break;
  133.       }
  134.       break;
  135.  
  136.     case KW_CALL:
  137.     case KW_GOTO:
  138.       t = 0;
  139.       if(token_type == TOK_IDENTIFIER || token_type == TOK_LOCAL_ID) {
  140.     symtype =
  141.       (token_type == TOK_IDENTIFIER ? SYMTAB_GLOBAL : SYMTAB_LOCAL);
  142.  
  143.     if(symtype == SYMTAB_LOCAL && local_level == 0) {
  144.       error(1, "Local symbol outside a LOCAL block");
  145.       return FAIL;
  146.     }
  147.  
  148.     sym = lookup_symbol(token_string, symtype);
  149.     if(sym == NULL || sym->type == SYM_FORWARD) {
  150.       if(sym == NULL) {
  151.         sym = add_symbol(token_string, symtype);
  152.         sym->type = SYM_FORWARD;
  153.       }
  154.  
  155.       val = 0;
  156.       add_patch(symtype, sym,
  157.             (op == KW_CALL ? PATCH8 : PATCH9));
  158.       t = 1;
  159.       get_token();
  160.       goto gen_goto_call;
  161.     }
  162.       }
  163.  
  164.       val = get_expression();
  165.       if(expr_error)
  166.     return FAIL;
  167.  
  168.       if(val < 0 || val >= prog_mem_size)
  169.     error(0, "GOTO/CALL address out of range");
  170.  
  171.       if(op == KW_CALL && (val & 0x100) != 0)
  172.     error(0, "CALL address in upper half of a page");
  173.  
  174. gen_goto_call:
  175.       switch(op) {
  176.         case KW_CALL: gen_code(0x900 | (val & 0xff)); break;
  177.     case KW_GOTO: gen_code(0xa00 | (val & 0x1ff)); break;
  178.       }
  179.       if(t)
  180.     list_flags |= LIST_FORWARD;
  181.       break;
  182.  
  183.     case KW_TRIS:
  184.       t = get_expression();
  185.       if(expr_error)
  186.     return FAIL;
  187.       if(t != 5 && t != 6 && t != 7)
  188.     error(0, "Invalid register address for TRIS");
  189.       gen_code(0x000 | t);
  190.       break;
  191.  
  192. /*
  193.  * RETLW allows multiple parameters/strings, for generating lookup tables
  194.  */
  195.     case KW_RETLW:
  196.       for(;;) {
  197.     if(token_type == TOK_STRCONST) {
  198.       for(cp = token_string; *cp != '\0'; cp++)
  199.         gen_code(0x800 | (int)((unsigned char)(*cp)));
  200.       get_token();
  201.     } else {
  202.       if(gen_byte_c(0x800) != OK)
  203.         return FAIL;
  204.     }
  205.  
  206.     if(token_type != TOK_COMMA)
  207.       break;
  208.  
  209.     get_token();
  210.       }
  211.       break;
  212.  
  213.     case KW_NOP:
  214.       gen_code(0x000);
  215.       break;
  216.  
  217.     case KW_CLRW:
  218.       gen_code(0x040);
  219.       break;
  220.  
  221.     case KW_OPTION:
  222.       gen_code(0x002);
  223.       break;
  224.  
  225.     case KW_SLEEP:
  226.       gen_code(0x003);
  227.       break;
  228.  
  229.     case KW_CLRWDT:
  230.       gen_code(0x004);
  231.       break;
  232.  
  233.     case KW_RETURN:
  234.     case KW_RETFIE:
  235.     case KW_ADDLW:
  236.     case KW_SUBLW:
  237.       error(1, "Unimplemented instruction for PIC%s", pic_type->name);
  238.       return FAIL;
  239.  
  240.     default:
  241.       error(1, "Syntax error");
  242.       return FAIL;
  243.   }
  244.  
  245.   return OK;
  246. }
  247.  
  248.